{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 前言\n",
    "\n",
    "通过 Pandas 可以方便的读取 CSV 文件。\n",
    "\n",
    "# 什么是 CSV 文件？\n",
    "\n",
    "CSV是最通用的一种文件格式，它可以非常容易地被导入各种PC表格及数据库中，你在 EXCEL 里面就可以导出这样一个文件，我们可以试试。\n",
    "\n",
    "而我们熟悉的XLS则是EXCEL专用格式。 CSV文件一行即为数据表的一行，生成数据表字段用半角逗号隔开。因此 Comma Separated Value即是CSV的全称，你可以尝试用记事本打开CSV和XLS文件看看。\n",
    "\n",
    "\n",
    "# 操作-读取\n",
    "\n",
    "用 Pandas 读取 CSV 非常特别简单。\n",
    "\n",
    "1. 导入 pandas 包\n",
    "2. 一行代码`pd.read_csv()`+文件地址，再赋值给一个变量，我们习惯命名为 `df`\n",
    "3. 打印出来看看结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/Users/davidfnck/Downloads/课件-PPT课程/第2期PPT及邮件营销课程/Python Tutorial for Humans™/003-学习 Pandas'"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如何获取绝对路径\n",
    "# import os\n",
    "# os.getcwd( ) # 获取现在目录\n",
    "\n",
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "      Unnamed: 0    ts_code  symbol  name area industry  list_date\n",
      "0              0  000001.SZ       1  平安银行   深圳       银行   19910403\n",
      "1              1  000002.SZ       2   万科A   深圳     全国地产   19910129\n",
      "2              2  000004.SZ       4  国农科技   深圳     生物制药   19910114\n",
      "3              3  000005.SZ       5  世纪星源   深圳     环境保护   19901210\n",
      "4              4  000006.SZ       6  深振业A   深圳     区域地产   19920427\n",
      "...          ...        ...     ...   ...  ...      ...        ...\n",
      "3719        3719  688366.SH  688366  昊海生科   上海     生物制药   20191030\n",
      "3720        3720  688368.SH  688368  晶丰明源   上海      半导体   20191014\n",
      "3721        3721  688369.SH  688369  致远互联   北京     软件服务   20191031\n",
      "3722        3722  688388.SH  688388  嘉元科技   广东      元器件   20190722\n",
      "3723        3723  688389.SH  688389  普门科技   深圳     医疗保健   20191105\n",
      "\n",
      "[3724 rows x 7 columns]\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd \n",
    "\n",
    "# 读取 CSV，这个 stock_basic.csv 文件是从 tushare 直接下载的股票基本数据，读取一下试试\n",
    "## 如何获取文件的位置？\n",
    "### 绝对位置：/Users/davidfnck/Downloads/CSVFiles/stock_basic.csv\n",
    "### 相对位置：CSVFiles/stock_basic.csv  # 在本程序所在文件夹开始算位置，同一级是 ./ ，上一级是 ../\n",
    "df = pd.read_csv('CSVFiles/stock_basic.csv')\n",
    "print(df)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3724 entries, 0 to 3723\n",
      "Data columns (total 7 columns):\n",
      "Unnamed: 0    3724 non-null int64\n",
      "ts_code       3724 non-null object\n",
      "symbol        3724 non-null int64\n",
      "name          3724 non-null object\n",
      "area          3722 non-null object\n",
      "industry      3722 non-null object\n",
      "list_date     3724 non-null int64\n",
      "dtypes: int64(3), object(4)\n",
      "memory usage: 203.8+ KB\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "print(df.info()) # 我们也可以看一下这张 DataFrame 的基本属性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 问题解读\n",
    "\n",
    "我们看上面打印出来的结果有什么问题？\n",
    "\n",
    "1. pandas 识别到 CSV 的第一行包含列名，并自动使用它们\n",
    "\n",
    "2. pandas 也在 DataFrame 中使用从零开始的整数索引，那是因为没有告诉它我们的索引应该是什么\n",
    "\n",
    "3. 第一列（我们这里的 index 不算一列）的标题，是`Unnanmed: 0`，这是什么？打开源文件看一下，我们发现这是我们当时将 DataFrame 写入文件的时候，index 同时写入留下的\n",
    "\n",
    "4. 第三列`symbol`原先的`000001`变成了`1`，前面的`0`全部被省略了\n",
    "\n",
    "5. 最后一列`list_date`是表示时间，但是格式却是数字\n",
    "\n",
    "让我们接下来解决这些问题。\n",
    "\n",
    "要使用其他列作为 DataFrame 的索引，添加 index_col 可选参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "        ts_code  symbol  name area industry  list_date\n",
      "0     000001.SZ       1  平安银行   深圳       银行   19910403\n",
      "1     000002.SZ       2   万科A   深圳     全国地产   19910129\n",
      "2     000004.SZ       4  国农科技   深圳     生物制药   19910114\n",
      "3     000005.SZ       5  世纪星源   深圳     环境保护   19901210\n",
      "4     000006.SZ       6  深振业A   深圳     区域地产   19920427\n",
      "...         ...     ...   ...  ...      ...        ...\n",
      "3719  688366.SH  688366  昊海生科   上海     生物制药   20191030\n",
      "3720  688368.SH  688368  晶丰明源   上海      半导体   20191014\n",
      "3721  688369.SH  688369  致远互联   北京     软件服务   20191031\n",
      "3722  688388.SH  688388  嘉元科技   广东      元器件   20190722\n",
      "3723  688389.SH  688389  普门科技   深圳     医疗保健   20191105\n",
      "\n",
      "[3724 rows x 6 columns]\n"
     ]
    }
   ],
   "source": [
    "df = pd.read_csv('CSVFiles/stock_basic.csv',index_col=0)\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来，我们看到`symbol`字段的数据类型是`int`，我们希望它是字符串格式从文件中原封不动地读取出来，这样才不会省略前面的`0`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "        ts_code  symbol  name area industry  list_date\n",
      "0     000001.SZ  000001  平安银行   深圳       银行   19910403\n",
      "1     000002.SZ  000002   万科A   深圳     全国地产   19910129\n",
      "2     000004.SZ  000004  国农科技   深圳     生物制药   19910114\n",
      "3     000005.SZ  000005  世纪星源   深圳     环境保护   19901210\n",
      "4     000006.SZ  000006  深振业A   深圳     区域地产   19920427\n",
      "...         ...     ...   ...  ...      ...        ...\n",
      "3719  688366.SH  688366  昊海生科   上海     生物制药   20191030\n",
      "3720  688368.SH  688368  晶丰明源   上海      半导体   20191014\n",
      "3721  688369.SH  688369  致远互联   北京     软件服务   20191031\n",
      "3722  688388.SH  688388  嘉元科技   广东      元器件   20190722\n",
      "3723  688389.SH  688389  普门科技   深圳     医疗保健   20191105\n",
      "\n",
      "[3724 rows x 6 columns]\n"
     ]
    }
   ],
   "source": [
    "df = pd.read_csv('CSVFiles/stock_basic.csv',index_col=0,dtype={'symbol':'str'})\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来，让我们修复`list_date`字段的数据类型。可以使用 `parse_dates` 可选参数强制 pandas 将数据作为日期读取，该参数定义为要作为日期处理的列名列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "        ts_code  symbol  name area industry  list_date\n",
      "0     000001.SZ       1  平安银行   深圳       银行 1991-04-03\n",
      "1     000002.SZ       2   万科A   深圳     全国地产 1991-01-29\n",
      "2     000004.SZ       4  国农科技   深圳     生物制药 1991-01-14\n",
      "3     000005.SZ       5  世纪星源   深圳     环境保护 1990-12-10\n",
      "4     000006.SZ       6  深振业A   深圳     区域地产 1992-04-27\n",
      "...         ...     ...   ...  ...      ...        ...\n",
      "3719  688366.SH  688366  昊海生科   上海     生物制药 2019-10-30\n",
      "3720  688368.SH  688368  晶丰明源   上海      半导体 2019-10-14\n",
      "3721  688369.SH  688369  致远互联   北京     软件服务 2019-10-31\n",
      "3722  688388.SH  688388  嘉元科技   广东      元器件 2019-07-22\n",
      "3723  688389.SH  688389  普门科技   深圳     医疗保健 2019-11-05\n",
      "\n",
      "[3724 rows x 6 columns]\n"
     ]
    }
   ],
   "source": [
    "df = pd.read_csv('CSVFiles/stock_basic.csv',index_col=0,dtype={'symbol':'str'},parse_dates=['list_date'])\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果 CSV 文件的第一行中没有列名，则可以使用 `names` 可选参数来提供列名的列表。 如果要覆盖第一行中提供的列名，也可以使用此选项。 在这种情况下，还必须使用`header = 0`可选参数告诉 `pandas.read_csv()`忽略现有列名："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "           市场编号    股票代码  股票名称 所在城市    行业       上市时间\n",
      "0     000001.SZ  000001  平安银行   深圳    银行 1991-04-03\n",
      "1     000002.SZ  000002   万科A   深圳  全国地产 1991-01-29\n",
      "2     000004.SZ  000004  国农科技   深圳  生物制药 1991-01-14\n",
      "3     000005.SZ  000005  世纪星源   深圳  环境保护 1990-12-10\n",
      "4     000006.SZ  000006  深振业A   深圳  区域地产 1992-04-27\n",
      "...         ...     ...   ...  ...   ...        ...\n",
      "3719  688366.SH  688366  昊海生科   上海  生物制药 2019-10-30\n",
      "3720  688368.SH  688368  晶丰明源   上海   半导体 2019-10-14\n",
      "3721  688369.SH  688369  致远互联   北京  软件服务 2019-10-31\n",
      "3722  688388.SH  688388  嘉元科技   广东   元器件 2019-07-22\n",
      "3723  688389.SH  688389  普门科技   深圳  医疗保健 2019-11-05\n",
      "\n",
      "[3724 rows x 6 columns]\n"
     ]
    }
   ],
   "source": [
    "df = pd.read_csv('CSVFiles/stock_basic.csv', \n",
    "            index_col=0, \n",
    "            dtype={'股票代码':'str'},\n",
    "            parse_dates=['上市时间'], \n",
    "            header=0, \n",
    "            names=['市场编号', '股票代码','股票名称', '所在城市','行业','上市时间'])\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "请注意，由于列名称已更改，因此还必须更改`symbol`和`parse_dates`可选参数中指定的列。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 代码解读\n",
    "\n",
    "当然，我们解决这些问题最根本的方法，还是回到`pd.read_csv`这句代码上去，正好我们也借此机会再来读一读源码。\n",
    "\n",
    "查看代码参数的方法：`pandas.read_csv`+`shift+tab`\n",
    "\n",
    "链接：https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html\n",
    "术语参照：https://docs.python.org/zh-cn/3.7/glossary.html\n",
    "\n",
    "```python\n",
    "pandas.read_csv(\n",
    "    filepath_or_buffer: Union[str, pathlib.Path, IO[~AnyStr]],   #  str，pathlib。str, pathlib.Path, py._path.local.LocalPath or any object with a read() method (such as a file handle or StringIO)\n",
    "    # 可以是URL，可用URL类型包括：http, ftp, s3和文件。对于多文件正在准备中。本地文件读取实例：://localhost/path/to/table.csv\n",
    "    # 参数名字本身反映了功能\n",
    "        # + 这里可以接受一个文件名，或者一个URL，\n",
    "        # + 也可以接受一个打开的文件句柄，\n",
    "        # + 或者其他任何提供了read方法的对象，\n",
    "        # + 举个栗子：某个URL输出CSV，但是需要验证密码，那么就没法让 read_csv 直接读取URL，但是可以使用 urlopen 发送附带了验证信息的Request，并把返回的 Response 对象传给 read_csv 函数，进而通过 Response 对象的 read 方法加载数据；\n",
    "    \n",
    "    sep=',',   # str, default ‘,’\n",
    "    # 指定分隔符。如果不指定参数，则会尝试使用逗号分隔。（分隔符长于一个字符并且不是‘\\s+’,将使用python的语法分析器。并且忽略数据中的逗号。正则表达式例子：'\\r\\t'。不想适可而止的同学，要去学习一下正则表达式。）\n",
    "    \n",
    "    delimiter=None,   # str, default None\n",
    "    # 定界符，备选分隔符（如果指定该参数，则sep参数失效）\n",
    "    # `delimiter`是`sep`的别名；如果指定为 `\\t（制表符）`的话，就可以实现 `read_table` 的默认功能；支持使用正则表达式来匹配某些不标准的CSV文件；\n",
    "    \n",
    "    # Column and Index Locations and Names\n",
    "    # 列和索引的位置和名称\n",
    "    header='infer',  # int or list of ints, default ‘infer’\n",
    "    # 指定行数用来作为列名，数据开始行数。如果文件中没有列名，则默认为0，否则设置为None。如果明确设定header=0 就会替换掉原来存在列名。header参数可以是一个list例如：[0,1,3]，这个list表示将文件中的这些行作为列标题（意味着每一列有多个标题），介于中间的行将被忽略掉（例如本例中的2；本例中的数据1,2,4行将被作为多级标题出现，第3行数据将被丢弃，dataframe的数据从第5行开始。）。注意：如果skip_blank_lines=True 那么header参数忽略注释行和空行，所以header=0表示第一行数据而不是文件的第一行。\n",
    "    \n",
    "    names=None,  # array-like, default None\n",
    "    # 用于结果的列名列表，如果数据文件中没有列标题行，就需要执行header=None。默认列表中不能出现重复，除非设定参数mangle_dupe_cols=True。 \n",
    "    \n",
    "    index_col=None,   #  int or sequence or False, default None\n",
    "    # 用作行索引的列编号或者列名，如果给定一个序列则有多个行索引。如果文件不规则，行尾有分隔符，则可以设定index_col=False 来是的pandas不适用第一列作为行索引。\n",
    "    \n",
    "    usecols=None,   # array-like, default None\n",
    "    # 返回一个数据子集，该列表中的值必须可以对应到文件中的位置（数字可以对应到指定的列）或者是字符传为文件中的列名。例如：usecols有效参数可能是 [0,1,2]或者是 [‘foo’, ‘bar’, ‘baz’]。使用这个参数可以加快加载速度并降低内存消耗。\n",
    "    \n",
    "    squeeze=False,   # boolean, default False\n",
    "    # 如果文件只包含一列，则返回一个Series\n",
    "    \n",
    "    prefix=None,   # str, default None\n",
    "    # 在没有列标题时，给列添加前缀。例如：添加‘X’ 成为 X0, X1, ...\n",
    "    \n",
    "    mangle_dupe_cols=True,  # boolean, default True\n",
    "    # 重复的列，将‘X’...’X’表示为‘X.0’...’X.N’。如果设定为false则会将所有重名列覆盖。\n",
    "    \n",
    "    # General Parsing Configuration\n",
    "    # 常规解析配置\n",
    "    dtype=None,   # Type name or dict of column -> type, default None\n",
    "    # 每列数据的数据类型。例如 {‘a’: np.float64, ‘b’: np.int32}\n",
    "    \n",
    "    engine=None,  # {‘c’, ‘python’}, optional\n",
    "    # 使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。\n",
    "    \n",
    "    converters=None,  # dict, default None\n",
    "    # 列转换函数的字典。key可以是列名或者列的序号。\n",
    "    \n",
    "    true_values=None,  # list, default None\n",
    "    # Values to consider as True\n",
    "    \n",
    "    false_values=None,  # list, default None\n",
    "    # Values to consider as False\n",
    "    \n",
    "    skipinitialspace=False,  # boolean, default False\n",
    "    # 忽略分隔符后的空白（默认为False，即不忽略）\n",
    "    \n",
    "    skiprows=None,  # list-like or integer, default None\n",
    "    # 需要忽略的行数（从文件开始处算起），或需要跳过的行号列表（从0开始）。\n",
    "    \n",
    "    skipfooter=0,  # int, default 0\n",
    "    # 从文件尾部开始忽略。 (c引擎不支持)\n",
    "    \n",
    "    nrows=None,  # int, default None\n",
    "    # 需要读取的行数（从文件头开始算起）。\n",
    "    \n",
    "    # NA and Missing Data Handling\n",
    "    # 空值和缺失数据处理\n",
    "    na_values=None,  # scalar, str, list-like, or dict, default None\n",
    "    # 一组用于替换NA/NaN的值。如果传参，需要制定特定列的空值。默认为‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘nan’`.\n",
    "    \n",
    "    keep_default_na=True,  # bool, default True\n",
    "    # 如果指定na_values参数，并且keep_default_na=False，那么默认的NaN将被覆盖，否则添加。\n",
    "    \n",
    "    na_filter=True,  # boolean, default True\n",
    "    # 是否检查丢失值（空字符串或者是空值）。对于大文件来说数据集中没有空值，设定na_filter=False可以提升读取速度。\n",
    "    \n",
    "    verbose=False,  # boolean, default False\n",
    "    # 是否打印各种解析器的输出信息，例如：“非数值列中缺失值的数量”等。\n",
    "    \n",
    "    skip_blank_lines=True,  # boolean, default True\n",
    "    # 如果为True，则跳过空行；否则记为NaN。\n",
    "    \n",
    "    # Datetime Handling\n",
    "    # 日期时间处理\n",
    "    parse_dates=False,  #  boolean or list of ints or names or list of lists or dict, default False。这个参数指定对CSV文件中日期序列的处理方式：\n",
    "    # boolean. True -> 解析索引，默认为False，原样加载，不解析日期时间，可以为True，尝试解析日期索引，\n",
    "    # list of ints or names. e.g. If [1, 2, 3] -> 可以为数字或 names 的列表，解析指定的列为时间序列，解析1,2,3列的值作为独立的日期列；\n",
    "    # list of lists. e.g. If [[1, 3]] -> 可以为以列表为元素的列表，解析每个子列表中的字段组合为时间序列，合并1,3列作为一个日期列使用\n",
    "    # dict, e.g. {‘foo’ : [1, 3]} -> 可以为值为列表的字典，解析每个列表中的字段组合为时间序列，并命名为字典中对应的键值；将1,3列合并，并给合并后的列起名为\"foo\" \n",
    "\n",
    "    \n",
    "    infer_datetime_format=False,  # boolean, default False\n",
    "    # 如果设定为True并且 parse_dates 可用，那么pandas将尝试转换为日期类型，如果可以转换，转换方法并解析。在某些情况下会快5~10倍。\n",
    "    \n",
    "    keep_date_col=False,  # boolean, default False\n",
    "    # 如果连接多列解析日期，则保持参与连接的列。默认为False。\n",
    "    # 解析出日期序列后，是否保留原来的列；\n",
    "    \n",
    "    date_parser=None,  # function, default None\n",
    "    # 用于解析日期的函数，默认使用dateutil.parser.parser来做转换。Pandas尝试使用三种不同的方式解析，如果遇到问题则使用下一种方式。\n",
    "    # 1.使用一个或者多个arrays（由parse_dates指定）作为参数；\n",
    "    # 2.连接指定多列字符串作为一个列作为参数；\n",
    "    # 3.每行调用一次date_parser函数来解析一个或者多个字符串（由parse_dates指定）作为参数。\n",
    "    \n",
    "    dayfirst=False,  # boolean, default False\n",
    "    # DD/MM格式的日期类型\n",
    "    \n",
    "    cache_dates=True,  \n",
    "    \n",
    "    \n",
    "    # Iteration\n",
    "    # 迭代\n",
    "    iterator=False,  # boolean, default False\n",
    "    # 返回一个TextFileReader 对象，以便逐块处理文件。\n",
    "    \n",
    "    chunksize=None,  # int, default None\n",
    "    # 文件块的大小\n",
    "    \n",
    "    # Quoting, Compression, and File Format\n",
    "    # 引用，压缩和文件格式\n",
    "    compression='infer',  # {‘infer’, ‘gzip’, ‘bz2’, ‘zip’, ‘xz’, None}, default ‘infer’\n",
    "    # 直接使用磁盘上的压缩文件。如果使用infer参数，则使用 gzip, bz2, zip或者解压文件名中以‘.gz’, ‘.bz2’, ‘.zip’, or ‘xz’这些为后缀的文件，否则不解压。如果使用zip，那么ZIP包中国必须只包含一个文件。设置为None则不解压。新版本0.18.1版本支持zip和xz解压\n",
    "    \n",
    "    thousands=None,  # str, default None\n",
    "    # 千分位分割符，如“，”或者“.\"\n",
    "    \n",
    "    decimal=b'.',  # str, default ‘.’\n",
    "    # 字符中的小数点 (例如：欧洲数据使用’，‘).\n",
    "    \n",
    "    lineterminator=None,  # str (length 1), default None\n",
    "    # 行分割符，只在C解析器下使用。\n",
    "    \n",
    "    quotechar='\"',  #  str (length 1), optional\n",
    "    # 引号，用作标识开始和解释的字符，引号内的分割符将被忽略。\n",
    "    \n",
    "    quoting=0,  # int or csv.QUOTE_* instance, default 0\n",
    "    # 控制csv中的引号常量。可选 QUOTE_MINIMAL (0), QUOTE_ALL (1), QUOTE_NONNUMERIC (2) or QUOTE_NONE (3)\n",
    "    \n",
    "    doublequote=True,  # boolean, default True\n",
    "    # 双引号，当单引号已经被定义，并且quoting 参数不是QUOTE_NONE的时候，使用双引号表示引号内的元素作为一个元素使用。\n",
    "    \n",
    "    escapechar=None,  # str (length 1), default None\n",
    "    # 当quoting 为QUOTE_NONE时，指定一个字符使的不受分隔符限值。\n",
    "    \n",
    "    comment=None,  # str, default None\n",
    "    # 标识着多余的行不被解析。如果该字符出现在行首，这一行将被全部忽略。这个参数只能是一个字符，空行（就像skip_blank_lines=True）注释行被header和skiprows忽略一样。例如如果指定comment='#' 解析‘#empty\\na,b,c\\n1,2,3’ 以header=0 那么返回结果将是以’a,b,c'作为header。\n",
    "    \n",
    "    encoding=None,  # str, default None\n",
    "    # 指定字符集类型，通常指定为'utf-8'.\n",
    "    \n",
    "    dialect=None, # str or csv.Dialect instance, default None\n",
    "    # 如果没有指定特定的语言，如果sep大于一个字符则忽略。具体查看csv.Dialect 文档\n",
    "    \n",
    "    # Error Handling\n",
    "    # 错误处理\n",
    "    error_bad_lines=True,  # boolean, default True\n",
    "    # 如果一行包含太多的列，那么默认不会返回DataFrame ，如果设置成false，那么会将改行剔除（只能在C解析器下使用）。\n",
    "    \n",
    "    warn_bad_lines=True,  # boolean, default True\n",
    "    # 如果error_bad_lines =False，并且warn_bad_lines =True 那么所有的“bad lines”将会被输出（只能在C解析器下使用）。\n",
    "    \n",
    "    # Internal\n",
    "    # 内部\n",
    "    delim_whitespace=False, \n",
    "    low_memory=True,  # boolean, default True\n",
    "    # 分块加载到内存，再低内存消耗中解析。但是可能出现类型混淆。确保类型不被混淆需要设置为False。或者使用dtype 参数指定类型。注意使用chunksize 或者iterator 参数分块读入会将整个文件读入到一个Dataframe，而忽略类型（只能在C解析器中有效）\n",
    "    memory_map=False,  # boolean, default False\n",
    "    # 如果使用的文件在内存内，那么直接map文件使用。使用这种方式可以避免文件再次进行IO操作。\n",
    "    float_precision=None  # string, default None\n",
    "    # Specifies which converter the C engine should use for floating-point values. The options are None for the ordinary converter, high for the high-precision converter, and round_trip for the round-trip converter.\n",
    ")\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实例演示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 演示分隔符\n",
    "\n",
    "## 如果不明确的话，原始读出来是多行一列，没有分割开\n",
    "# df_sep = pd.read_csv('CSVFiles/read_csv_header.csv')\n",
    "\n",
    "## 在文件中间隔随意添加 # 作为间隔\n",
    "df_sep = pd.read_csv('CSVFiles/read_csv_sep.csv',sep='#',delimiter=',')\n",
    "\n",
    "print(df_sep)\n",
    "print(df_sep.shape)\n",
    "print(df_sep.info())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   one  two  three  twoa  threea\n",
      "0  1.0  2.0    3.0   4.0     5.0\n",
      "1  3.0  NaN    NaN   NaN     NaN\n",
      "2  NaN  NaN    NaN   NaN     NaN\n",
      "3  1.0  2.0    3.0   4.0     5.0\n",
      "4  NaN  2.0    NaN   NaN     NaN\n",
      "5  1.0  2.0    3.0   4.0     5.0\n",
      "6  1.0  NaN    NaN   NaN     NaN\n",
      "7  NaN  NaN    NaN   NaN     NaN\n",
      "8  1.0  2.0    3.0   4.0     5.0\n",
      "(9, 5)\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 9 entries, 0 to 8\n",
      "Data columns (total 5 columns):\n",
      "one       6 non-null float64\n",
      "two       5 non-null float64\n",
      "three     4 non-null float64\n",
      "twoa      4 non-null float64\n",
      "threea    4 non-null float64\n",
      "dtypes: float64(5)\n",
      "memory usage: 488.0 bytes\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 演示列和索引的位置和名称\n",
    "\n",
    "## 如果不明确的话，原始读出来是多行一列，没有分割开\n",
    "# df_header = pd.read_csv('CSVFiles/read_csv_header.csv',header=[1,4],skip_blank_lines=False)\n",
    "\n",
    "## 如果跳过空行，默认是跳过，则是数据的第一行\n",
    "df_header = pd.read_csv('CSVFiles/read_csv_header.csv',names=['one','two','three','twoa','threea'],skip_blank_lines=False)\n",
    "\n",
    "print(df_header)\n",
    "print(df_header.shape)\n",
    "print(df_header.info())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   1\n",
      "0  2\n",
      "1  3\n",
      "2  4\n",
      "3  5\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "(4, 1)\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 4 entries, 0 to 3\n",
      "Data columns (total 1 columns):\n",
      "1    4 non-null int64\n",
      "dtypes: int64(1)\n",
      "memory usage: 160.0 bytes\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 如果文件只包含一列，则返回一个Series\n",
    "df_squeeze = pd.read_csv('CSVFiles/read_csv_squeeze.csv',squeeze=False)\n",
    "\n",
    "print(df_squeeze)\n",
    "print(type(df_squeeze))\n",
    "print(df_squeeze.shape)\n",
    "print(df_squeeze.info())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 操作-写入\n",
    "\n",
    "用 Pandas 写入 CSV 非常特别简单。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "           市场编号    股票代码  股票名称 所在城市    行业       上市时间\n",
      "0     000001.SZ  000001  平安银行   深圳    银行 1991-04-03\n",
      "1     000002.SZ  000002   万科A   深圳  全国地产 1991-01-29\n",
      "2     000004.SZ  000004  国农科技   深圳  生物制药 1991-01-14\n",
      "3     000005.SZ  000005  世纪星源   深圳  环境保护 1990-12-10\n",
      "4     000006.SZ  000006  深振业A   深圳  区域地产 1992-04-27\n",
      "...         ...     ...   ...  ...   ...        ...\n",
      "3719  688366.SH  688366  昊海生科   上海  生物制药 2019-10-30\n",
      "3720  688368.SH  688368  晶丰明源   上海   半导体 2019-10-14\n",
      "3721  688369.SH  688369  致远互联   北京  软件服务 2019-10-31\n",
      "3722  688388.SH  688388  嘉元科技   广东   元器件 2019-07-22\n",
      "3723  688389.SH  688389  普门科技   深圳  医疗保健 2019-11-05\n",
      "\n",
      "[3724 rows x 6 columns]\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "Writing 6 cols but got 5 aliases",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-6-2aa4e1b93ced>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;31m# 写入\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'CSVFiles/stock_basic_new.csv'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mheader\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'编号'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'代码'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'名称'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'城市'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'行业'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/pandas/core/generic.py\u001b[0m in \u001b[0;36mto_csv\u001b[0;34m(self, path_or_buf, sep, na_rep, float_format, columns, header, index, index_label, mode, encoding, compression, quoting, quotechar, line_terminator, chunksize, date_format, doublequote, escapechar, decimal)\u001b[0m\n\u001b[1;32m   3226\u001b[0m             \u001b[0mdecimal\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdecimal\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   3227\u001b[0m         )\n\u001b[0;32m-> 3228\u001b[0;31m         \u001b[0mformatter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msave\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   3229\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   3230\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mpath_or_buf\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/pandas/io/formats/csvs.py\u001b[0m in \u001b[0;36msave\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    200\u001b[0m                 \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwriter\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mUnicodeWriter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mwriter_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    201\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 202\u001b[0;31m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_save\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    203\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    204\u001b[0m         \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/pandas/io/formats/csvs.py\u001b[0m in \u001b[0;36m_save\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    308\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m_save\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    309\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 310\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_save_header\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    311\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    312\u001b[0m         \u001b[0mnrows\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata_index\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/pandas/io/formats/csvs.py\u001b[0m in \u001b[0;36m_save_header\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    240\u001b[0m                     (\n\u001b[1;32m    241\u001b[0m                         \u001b[0;34m\"Writing {ncols} cols but got {nalias} \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 242\u001b[0;31m                         \u001b[0;34m\"aliases\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mncols\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcols\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnalias\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mheader\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    243\u001b[0m                     )\n\u001b[1;32m    244\u001b[0m                 )\n",
      "\u001b[0;31mValueError\u001b[0m: Writing 6 cols but got 5 aliases"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df = pd.read_csv('CSVFiles/stock_basic.csv', \n",
    "            index_col=0, \n",
    "            dtype={'股票代码':'str'},\n",
    "            parse_dates=['上市时间'], \n",
    "            header=0, \n",
    "            names=['市场编号', '股票代码','股票名称', '所在城市','行业','上市时间'])\n",
    "print(df)\n",
    "\n",
    "# 写入\n",
    "df.to_csv('CSVFiles/stock_basic_new.csv',header=0,index=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 代码解读\n",
    "\n",
    "```python\n",
    "DataFrame.to_csv(self, \n",
    "                 path_or_buf=None,   #  str or file handle, default None\n",
    "                 # 字符串或文件句柄，默认无文件。路径或对象，如果没有提供，结果将返回为字符串。\n",
    "                 \n",
    "                 sep=', ',   # str, default ‘,’\n",
    "                 # 分隔符。长度为1的字符串。\n",
    "                 \n",
    "                 na_rep='',   # str, default ‘’\n",
    "                 # 替换空值。\n",
    "                 \n",
    "                 float_format=None,  #  str, default None\n",
    "                 # 浮点数格式，保留几位小数，例如 float_format='%.2f'\n",
    "                 \n",
    "                 columns=None,  # sequence（序列）, optional\n",
    "                 # 要写入文件的列，例如columns=['name']\n",
    "                 \n",
    "                 header=True,  # bool or list of str, default True\n",
    "                 # 是否保留列名。如果给出了字符串列表，则假定它是列名的别名。在版本0.24.0中更改：以前将Series默认为False。例如header=0，就是不保留列名，相当于 False\n",
    "                 \n",
    "                 index=True,  # boolean, default True\n",
    "                 # 是否保留行索引\n",
    "                 \n",
    "                 index_label=None, \n",
    "                 # 索引列的列标签（如果需要）。 如果没有给出，并且标头和索引为True，则使用索引名。 如果对象使用MultiIndex，则应给出一个序列。 如果为False，则不打印索引名称的字段。\n",
    "                 \n",
    "                 mode='w',  # str\n",
    "                 # Python写模式，默认“w”\n",
    "                 \n",
    "                 encoding=None,  # string, optional\n",
    "                 # 表示在输出文件中使用的编码的字符串\n",
    "                 \n",
    "                 compression='infer',  # str, default ‘infer’\n",
    "                 # 表示在输出文件中使用的压缩的字符串，允许值为“gzip”、“bz2”、“xz”，仅在第一个参数是文件名时使用。\n",
    "                 \n",
    "                 quoting=None,  # optional constant from csv module（ CSV模块的可选常量。）\n",
    "                 # 默认值为to_csv.QUOTE_MINIMAL。如果设置了浮点格式，那么浮点将转换为字符串，因此csv.QUOTE_NONNUMERIC会将它们视为非数值的。\n",
    "                 \n",
    "                 quotechar='\"', # string (length 1), default ‘”’（字符串（长度1），默认“”）\n",
    "                 # 用于引用字段的字符\n",
    "                 \n",
    "                 line_terminator=None,  # string, default ‘\\n’\n",
    "                 # 在输出文件中使用的换行字符或字符序列\n",
    "                 \n",
    "                 chunksize=None,  # int or None\n",
    "                 # 一次写入行\n",
    "                 \n",
    "                 date_format=None,  # string, default None\n",
    "                 # 字符串对象转换为日期时间对象\n",
    "                 \n",
    "                 doublequote=True,  # bool, default True\n",
    "                 # 控制字段内quotechar的引用。\n",
    "                 \n",
    "                 escapechar=None,  # str, default None\n",
    "                 # 长度为1的字符串。适当时用于转义sep和quotechar的字符。\n",
    "                 \n",
    "                 decimal='.'  # string, default ‘.’\n",
    "                 # Character recognized as decimal separator. E.g. use ‘,’ for European data.     \n",
    "                )\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
